﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace FotoAnotSharp.Gate
{
    public delegate void GateObjectPickedDelegate(GatePicker sender, GraphicalObject picked);

    public partial class GatePicker : UserControl
    {
        private Dictionary<GraphicalObject, GraphicalObjectNode> mNodeDictionary = new Dictionary<GraphicalObject, GraphicalObjectNode>();

        private Font mSelectionFont;

        public GatePicker()
        {
            InitializeComponent();

            mSelectionFont = new Font(Font, FontStyle.Underline);

            treeView1.DrawMode = TreeViewDrawMode.OwnerDrawText;
            treeView1.AfterSelect += new TreeViewEventHandler(treeView1_AfterSelect);
            treeView1.BeforeSelect += new TreeViewCancelEventHandler(treeView1_BeforeSelect);
            treeView1.DrawNode += new DrawTreeNodeEventHandler(treeView1_DrawNode);
        }

        void treeView1_DrawNode(object sender, DrawTreeNodeEventArgs e)
        {
            e.DrawDefault = true;
            if (e.State == TreeNodeStates.Selected)
            {
                e.DrawDefault = false;
                using (Brush br = new SolidBrush(treeView1.BackColor))
                    e.Graphics.FillRectangle(br, e.Bounds);
                e.Graphics.DrawString(e.Node.Text, mSelectionFont, Brushes.Black, e.Bounds.Left, e.Bounds.Top);
            }
        }

        void treeView1_BeforeSelect(object sender, TreeViewCancelEventArgs e)
        {

        }

        void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
        {
            if (e.Action == TreeViewAction.Expand || e.Action == TreeViewAction.Collapse)
                return;

            OnGateObjectPicked(e.Node == null ? null : (e.Node.Tag as GraphicalObjectNode).GOBject);
        }

        public event GateObjectPickedDelegate GateObjectPicked;

        public GraphicalObject SelectedObject
        {
            get
            {
                return treeView1.SelectedNode == null ? null : (treeView1.SelectedNode.Tag as GraphicalObjectNode).GOBject;
            }
            set
            {
                if (value == null)
                { SetSelectedNode(null); return; }

                GraphicalObjectNode node;
                if (!mNodeDictionary.TryGetValue(value, out node))
                    throw new InvalidOperationException("Picker has another model");

                SetSelectedNode(node.Node);
            }
        }

        private void SetSelectedNode(TreeNode n)
        {
            try
            {
                treeView1.BeginUpdate();

                treeView1.CollapseAll();
                treeView1.SelectedNode = n;
            }
            finally { treeView1.EndUpdate(); }
        }

        private void OnGateObjectPicked(GraphicalObject picked)
        {
            if (GateObjectPicked != null)
                GateObjectPicked(this, picked);
        }


        public void Clear()
        {
            treeView1.Nodes.Clear();
            mNodeDictionary.Clear();
        }

        public void LoadHiearchy(GraphicalObjectHiearchy h)
        {
            Clear();

            AddNode(h.Parent, treeView1.Nodes);
            
        }

        void AddNode(GraphicalObject obj, TreeNodeCollection nodes)
        {
            GraphicalObjectNode node;
            TreeNode nn = nodes.Add(obj.Name, obj.CommentOrName);
            nn.Tag = (node = new GraphicalObjectNode(obj, nn));

            mNodeDictionary[obj] = node;

            foreach (GraphicalObject o in obj.Ancestors)
                AddNode(o, nn.Nodes);
        }

        class GraphicalObjectNode
        {
            public GraphicalObject GOBject { get; private set; }
            public TreeNode Node { get; private set; }

            public GraphicalObjectNode(GraphicalObject g, TreeNode n)
            {
                GOBject = g;
                Node = n;
            }
        }
    }
}
